package com.zzc.springboot.mybatis.generator;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.ConstVal;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.zzc.zfast.mybatis.base.BaseEntity;

import java.util.Collections;
import java.util.Scanner;

/**
 * 逆向工程器
 * <a href="https://baomidou.com/pages/981406/">MyBatis-Plus 代码生成器（新）</a>
 *
 * @author zhenzicheng
 * @date 2023-04-26 15:47
 */
public class MyBatisPlusGenerator {

    /**
     * 项目根目录
     */
    private static final String PROJECT_ROOT_PATH = System.getProperty("user.dir");

    public static void main(String[] args) {
        // 1、数据源配置
        DataSourceConfig.Builder datasourceBuilder = new DataSourceConfig.Builder(
                "jdbc:mysql://192.144.230.205:3306/local/device_info?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=UTC",
                "zzc",
                "123456"
        );

        // 2、创建代码生成器对象
        FastAutoGenerator generator = FastAutoGenerator.create(datasourceBuilder);

        // 3、全局配置
        generator.globalConfig(builder -> {
            // 设置作者
            builder.author("zzc")
                    // 定义生成的实体类中日期类型，使用jdk1.8新日期类型，例如 LocalDateTime
                    .dateType(DateType.TIME_PACK)
                    // 注释时间策略
                    .commentDate("yyyy-MM-dd")
                    // 生成后是否打开资源管理器:否
                    .disableOpenDir()
                    // 开启 swagger 模式。如果开启，需要导入 swagger 的 pom 依赖
                    // .enableSwagger()
                    // 指定输出目录
                    .outputDir(PROJECT_ROOT_PATH + "/mybatis-plus/src/main/java");
        });

        // 4、包配置
        generator.packageConfig(builder -> {
            // 父包名. ===========1.手动修改设置===========
            builder.parent("com.zzc.springboot")
                    // 将要生成的模块名称. ===========2.手动修改设置===========
                    //	.moduleName("employee")
                    // 设置生成的 控制层 文件夹名称
                    .controller("controller")
                    // 设置生成的 实体类 文件夹名称
                    .entity("entity")
                    // 设置生成的 服务层 文件夹名称
                    .service("service")
                    // 设置生成的 映射层 文件夹名称
                    .mapper("mapper")
                    // mapper.xml 文件路径。单模块下，其他文件路径默认即可。 ;
                    .pathInfo(Collections.singletonMap(OutputFile.xml, PROJECT_ROOT_PATH + "/src/main/resources/mapper"));
        });

        // 5、策略配置
        generator.strategyConfig(builder -> {
            // 设置数据库表名称. 如果不设置，则会将数据库中所有表都生成。（注意：需要与数据库中表名称一致，前缀也需添加）
            // ===========3.手动修改设置。===========
            builder.addInclude(scanner("表名，多个英文逗号分割").split(","))
                    // 过滤表前缀，生成的类名会去掉这个前缀
                    //.addTablePrefix("ta_", "sf_", "sk_")
                    // Entity 层策略
                    // 是否生成 entity：是
                    .entityBuilder()
                    // 开启lombok
                    .enableLombok()
                    // 公共父类（整合zfast审计类）
                    .superClass(BaseEntity.class)
                    // 设置生成的实体类名称. 默认配置不带 Entity 后缀，我习惯添加上
                    .convertFileName(entityName -> entityName)
                    // 移除数据库 is_ 前缀映射实体，例如数据库中 is_delete -> 实体 delete
                    .enableRemoveIsPrefix()
                    // 开启实体时字段注解。 会在生成的实体类的字段上，添加注解： @TableField("nickname")
                    .enableTableFieldAnnotation()
                    // 设置主键Id生成策略，设置为默认的雪花算法(ASSIGN_ID)
                    .idType(IdType.AUTO)
                    // 逻辑删除字段名。（与数据库中字段对应）
                    .logicDeleteColumnName("deleted")
                    // 逻辑删除属性名（定义在实体中的属性），会在生成的实体类的字段上，添加注解：@TableLogic
                    .logicDeletePropertyName("deleteFlag")
                    // 会在实体类的该字段上追加注解 @TableField(value = "create_time", fill = FieldFill.INSERT)
                    // 由于使用了公共的审计类所以暂时不需要单独加
                    // .addTableFills(
                    //         new Column("create_time", FieldFill.INSERT),
                    //         new Column("update_time", FieldFill.INSERT_UPDATE))

                    // Mapper 层策略
                    .mapperBuilder()
                    // 开启 @Mapper 注解。 会在生成的 mapper 类上，添加注解：@Mapper
                    .enableMapperAnnotation()
                    // 启用 BaseResultMap 生成。 会在 mapper.xml 文件生成[通用查询映射结果]配置。
                    .enableBaseResultMap()
                    // 启用 BaseColumnList。 会在 mapper.xml 文件生成[通用查询结果列]配置
                    .enableBaseColumnList()
                    // .convertMapperFileName(entityName -> entityName + ConstVal.MAPPER) // 默认
                    // .formatXmlFileName("%sXml") // 默认

                    // Service 层策略
                    .serviceBuilder()
                    // 设置生成的实体类名称。 默认配置名称前有个I，我习惯添去掉
                    .convertServiceFileName(serviceName -> serviceName + ConstVal.SERVICE)
                    // .formatServiceFileName("%sService") // 也可以用转换实现

                    // Controller 层策略
                    .controllerBuilder()
                    // 开启 @RestController 注解。 会在生成的 Controller 类上，添加注解：@RestController
                    .enableRestStyle()

            // 开启驼峰转连字符
            // .enableHyphenStyle();
            ;
        });

        // 6. 模板引擎配置，默认为 Velocity , 可选模板引擎 Freemarker 或 Beetl
        generator.templateEngine(new FreemarkerTemplateEngine());

        generator.execute();

    }

    public static String scanner(String tip) {
        Scanner scanner =
                new Scanner(System.in);
        System.out.println("请输入" + tip + "：");
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotBlank(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "！");
    }

}
